/*
 * Copyright (c) 2006-2011, Petr Panteleyev
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without modification,
 * are permitted provided that the following conditions are met:
 *
 *    1. Redistributions of source code must retain the above copyright notice,
 *       this list of conditions and the following disclaimer.
 *    2. Redistributions in binary form must reproduce the above copyright notice,
 *       this list of conditions and the following disclaimer in the documentation
 *       and/or other materials provided with the distribution.
 *    3. The name of the author may not be used to endorse or promote products
 *       derived from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
 * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR
 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
 * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

package org.panteleyev.blogclient;
import java.awt.MediaTracker;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLConnection;
import java.util.ArrayList;
import java.util.TreeMap;

import javax.imageio.ImageIO;
import javax.swing.ImageIcon;

import org.panteleyev.flickr.FLUserProfile;
import org.panteleyev.gclient.GBUserProfile;
import org.panteleyev.livejournal.LJUserProfile;
import org.panteleyev.utilities.MD5;
import org.panteleyev.wordpress.WordPressUserProfile;

final public class UserProfileManager {
    private static TreeMap<String, UserProfile<?>> profiles = new TreeMap<>();
    private static UserProfile<?> defaultProfile;

    public static void loadProfiles() {
        profiles.clear();

        File fin = Options.getProfilesFile();
        if (!fin.exists()) {
            return;
        }

        try (ObjectInputStream in = new ObjectInputStream(new FileInputStream(fin))) {
            int count = in.readInt();
            for (int i = 0; i < count; ++i) {
                UserProfile<?> prof = (UserProfile<?>)in.readObject();
                if (prof != null) {
                    profiles.put(prof.getName(), prof);
                    if (prof.isDefaultProfile()) {
                        defaultProfile = prof;
                    }
                }
            }
        } catch (IOException | ClassNotFoundException ex) {
            MainClass.handleException(null, ex);
        }
    }

    public static void saveProfiles() {
        try (ObjectOutputStream out = new ObjectOutputStream(new FileOutputStream(Options.getProfilesFile()))) {
            ArrayList<UserProfile<?>> v = new ArrayList<>(profiles.values());
            out.writeInt(v.size());
            for (UserProfile<?> prof : v) {
                out.writeObject(prof);
            }
        } catch (Exception ex) {
            MainClass.handleException(null, ex);
        }
    }

    public static int getProfileCount() { return profiles.size(); }

    public static UserProfile<?> getProfile(String name) {
        return profiles.get(name);
    }

    public static void deleteProfile(UserProfile<?> prof) {
        if (prof == defaultProfile) {
            setDefaultProfile(null);
        }
        Options.deleteCachedData(prof);
        profiles.remove(prof.getName());
        saveProfiles();
    }

    public static ArrayList<String> getProfileNames() {
        return new ArrayList<>(profiles.keySet());
    }

    public static ArrayList<UserProfile<?>> getProfiles() {
        return new ArrayList<>(profiles.values());
    }

    public static UserProfile<?> getDefaultProfile() { return defaultProfile; }
    static void setDefaultProfile(UserProfile<?> prof) {
        for (UserProfile<?> p : profiles.values()) {
            if (p != prof) {
                p.setDefaultProfile(false);
            }
        }
        defaultProfile = prof;
    }

    public static String getDefaultProfileName() {
        return (defaultProfile == null)? "" : defaultProfile.getName();
    }

    public static String getDefaultProfileUserName() {
        return (defaultProfile == null)? "" : defaultProfile.getUserName();
    }

    public static void addProfile(UserProfile<?> prof) {
        profiles.put(prof.getName(), prof);
    }

    public static void updateProfile(String oldName, UserProfile<?> prof) {
        profiles.remove(oldName);
        addProfile(prof);
    }

    public static UserProfile<?> createUserProfile(UserProfileType type, String name, String server) {
        switch (type) {
            case LIVEJOURNAL:
                return new LJUserProfile(name, server);

            case GOOGLE:
                return new GBUserProfile(name, server);

            case WORDPRESSCOM:
                return new WordPressUserProfile(UserProfileType.WORDPRESSCOM, name, server);

            case WORDPRESSGEN:
                return new WordPressUserProfile(UserProfileType.WORDPRESSGEN, name, server);

            case FLICKR:
                return new FLUserProfile(name, server);

//            case JAVANET:
            default:
                return null;
        }
    }

    public static String checkProfileName(String newName, UserProfile<?> profile) {
        if (newName.length() == 0) {
            return "Profile name cannot be empty";
        } else {
            boolean b = (profile != null)? !newName.equals(profile.getName()) : true;
            if (b && (getProfile(newName) != null)) {
                return "Profile with this name already exists";
            }
        }

        return null;
    }

    synchronized
    public static void storeThumbnail(IPhotoUserProfile profile, URL url, BufferedImage bim) {
        File pictDir = new File(profile.getCacheDirectory(), profile.getImageCacheName());
        if (!pictDir.exists()) {
            pictDir.mkdir();
        }

        // Now store thumbnail
        try {
            String fName = MD5.encode(url.toString()) + ".png";
            File pictFile = new File(pictDir, fName);
            ImageIO.write(bim, "png", pictFile);
        } catch (Exception e) {
            MainClass.handleException(null, e);
        }
    }


    synchronized
    public static ImageIcon loadThumbnail(IPhotoUserProfile profile, String url) {
        try {
            return loadThumbnail(profile, new URL(url));
        } catch (MalformedURLException ex) {
            return null;
        }
    }

    synchronized
    public static ImageIcon loadThumbnail(IPhotoUserProfile profile, URL url) {
        File pictDir = new File(profile.getCacheDirectory(), profile.getImageCacheName());
        if (!pictDir.exists()) {
            return null;
        }

        String fName = MD5.encode(url.toString()) + ".png";
        File pictFile = new File(pictDir, fName);
        if (!pictFile.exists()) {
            return null;
        }

        ImageIcon image = new ImageIcon(pictFile.getAbsolutePath());
        if (image.getImageLoadStatus() != MediaTracker.COMPLETE) {
            return null;
        } else {
            return image;
        }
    }

    synchronized
    public static ImageIcon loadThumbnailFromNetwork(IPhotoUserProfile profile, String url) {
        try {
            return loadThumbnailFromNetwork(profile, new URL(url));
        } catch (IOException ignore) {
            return null;
        }
    }

    synchronized
    public static ImageIcon loadThumbnailFromNetwork(IPhotoUserProfile profile, URL url) {
        ImageIcon thumb = loadThumbnail(profile, url);
        if (thumb == null) {
            try {
                URLConnection conn = url.openConnection();
                BufferedImage bim = ImageIO.read(conn.getInputStream());
                thumb = new ImageIcon(bim);
                storeThumbnail(profile, url, bim);
            } catch (IOException ignore) {
            }
        }
        return thumb;
    }

}
